package rbac.impl;

import java.sql.Date;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import models.Zjlist;

import rbac.RbacException;
import rbac.RbacService;
import rbac.models.Privilege;
import rbac.models.Role;
import rbac.models.Session;
import rbac.models.User;
import utils.DateUtil;

public class DefaultRbacService implements RbacService {
	private HttpSession httpSession;
	private HttpServletRequest request;

	public DefaultRbacService(HttpServletRequest request) {
		this.request = request;
		this.httpSession = request.getSession();
	}

	@Override
	public boolean exists() throws RbacException {
		return getCurrentUser() != null;
	}

	/**
	 * 取得会话ID，从COOKIE中获取
	 */
	public String getSessionId() {
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals("sessionId")) {
					return cookie.getValue();
				}
			}
		}
		return null;
	}

	@Override
	public Object getCurrentUser() throws RbacException {
		String sessionId = getSessionId();
		if (sessionId == null) {
			return null;
		}

		try {
			Session session = Session.findFirst(Session.class, "sessionid=?",
					new Object[] { sessionId });
			if (session == null) {
				return null;
			} else {
				return session.getUser();
			}
		} catch (Exception ex) {
			throw new RbacException("查询用户资料过程出现错误", ex);
		}
	}

	/**
	 * 返回所有需要验证的权限
	 */
	@SuppressWarnings("unchecked")
	private List<Privilege> getAllPrivileges() throws RbacException {
		try {
			List<Privilege> privileges = (List<Privilege>) httpSession
					.getAttribute("SESSION_ALL_PRIVILEGES");
			if (privileges != null) {
				return privileges;
			}

			privileges = new ArrayList<Privilege>();

			privileges = Privilege.findAll(Privilege.class, " groupid = 0 ",null);

			httpSession.setAttribute("SESSION_ALL_PRIVILEGES", privileges);

			return privileges;
		} catch (Exception ex) {
			throw new RbacException("获取用户权限过程出现错误", ex);
		}
	}
	
	/**
	 * 返回当前所拥有的所有权限
	 */
	@SuppressWarnings("unchecked")
	private List<Privilege> getCurrentPrivileges() throws RbacException {
		try {
			List<Privilege> privileges = (List<Privilege>) httpSession
					.getAttribute("SESSION_PRIVILEGES");
			if (privileges != null) {
				return privileges;
			}

			privileges = new ArrayList<Privilege>();

			User user = (User) getCurrentUser();

			// 用户没定义角色
			if (user.getRoleids() == null
					|| user.getRoleids().trim().equals("")) {
				return privileges;
			}

			Map<String, String> tmp = new HashMap<String, String>();
			List<Role> roles = Role.findAll(Role.class, "id in ("
					+ user.getRoleids() + ") and privilegeids is not null",
					null);
			for (Role role : roles) {
				if (!role.getPrivilegeids().trim().equals("")) {
					for (String id : role.getPrivilegeids().trim().split(",")) {
						if (!tmp.containsKey(id)) {
							tmp.put(id, id);
						}
					}
				}
			}
			String ids = "";
			for (String id : tmp.keySet()) {
				ids += id + ",";
			}
			if (!ids.equals("")) {
				ids = ids.substring(0, ids.length() - 1);
				privileges = Privilege.findAll(Privilege.class, "id in (" + ids
						+ ")");
			}

			httpSession.setAttribute("SESSION_PRIVILEGES", privileges);

			return privileges;
		} catch (Exception ex) {
			throw new RbacException("获取用户权限过程出现错误", ex);
		}
	}

	/**
	 * 返回当前所拥有的控件权限
	 */
	@SuppressWarnings("unchecked")
	@Override
	public Map<String, Object> getCurrentCompPrivileges() throws RbacException {
		try {
			Map<String, Object> compPrivileges = (Map<String, Object>) httpSession
					.getAttribute("SESSION_COMP_PRIVILEGES");
			if (compPrivileges != null) {
				return compPrivileges;
			}

			List<Privilege> privileges = new ArrayList<Privilege>();

			User user = (User) getCurrentUser();

			// 用户没定义角色
			if (user.getRoleids() == null
					|| user.getRoleids().trim().equals("")) {
				return compPrivileges;
			}

			Map<String, String> tmp = new HashMap<String, String>();
			List<Role> roles = Role.findAll(Role.class, "id in ("
					+ user.getRoleids() + ") and privilegeids is not null",
					null);
			for (Role role : roles) {
				if (!role.getPrivilegeids().trim().equals("")) {
					for (String id : role.getPrivilegeids().trim().split(",")) {
						if (!tmp.containsKey(id)) {
							tmp.put(id, id);
						}
					}
				}
			}
			String ids = "";
			for (String id : tmp.keySet()) {
				ids += id + ",";
			}
			if (!ids.equals("")) {
				ids = ids.substring(0, ids.length() - 1);
				privileges = Privilege.findAll(Privilege.class, "id in (" + ids
						+ ") and groupid=1");
			}
			
			compPrivileges = new HashMap<String, Object>();
			for (Privilege privilege : privileges) {
				String urls = privilege.getUrls();
				if (urls == null || urls.trim().equals("")) {
					continue;
				}
				for (String url : urls.split("\r\n")) {
					compPrivileges.put(url, true);
				}
			}
			compPrivileges.put("SESSION_COMP_PRIVILEGES", true);

			httpSession.setAttribute("SESSION_COMP_PRIVILEGES", compPrivileges);

			return compPrivileges;
		} catch (Exception ex) {
			throw new RbacException("获取用户权限过程出现错误", ex);
		}
	}

	@Override
	public boolean isAllowed(String actionUrl) throws RbacException {
		if (needPrivilege(actionUrl) == false) return true;
		List<Privilege> privileges = getCurrentPrivileges();
		for (Privilege privilege : privileges) {
			String urls = privilege.getUrls();
			if (urls == null || urls.trim().equals("")) {
				continue;
			}
			for (String url : urls.split("\r\n")) {
				Pattern p = Pattern.compile(url, Pattern.CASE_INSENSITIVE);
				Matcher m = p.matcher(actionUrl);
				if (m.find()) {
					return true;
				}
			}
		}
		return false; // false 测试可选修改为 true 完成配置后再改回来
	}

	@Override
	public boolean needPrivilege(String actionUrl) throws RbacException{
		try{
		List<Privilege> privileges = getAllPrivileges();
		for (Privilege privilege : privileges) {
			String urls = privilege.getUrls();
			if (urls == null || urls.trim().equals("")) {
				continue;
			}
			for (String url : urls.split("\r\n")) {
				Pattern p = Pattern.compile(url, Pattern.CASE_INSENSITIVE);
				Matcher m = p.matcher(actionUrl);
				if (m.find()) {
					return true;
				}
			}
		}
		return false;
		} catch (Exception ex) {
			throw new RbacException("检查页面是否需要权限过程出现错误", ex);
		}
	}
	
	@Override
	public boolean hasPrivilege(String privilegeName) throws RbacException {
		List<Privilege> privileges = getCurrentPrivileges();
		for (Privilege privilege : privileges) {
			if (privilege.getName().equals(privilegeName)) {
				return true;
			}
		}
		return false;
	}

	@Override
	public Map<String, Object> login(String login, String pass)
			throws RbacException {
		logout();
		try {
			Map<String, Object> result = new HashMap<String, Object>();
			User user = User.findFirst(User.class, "login=? and password=? and (optime1 = '' or optime1 is null or CONVERT(varchar(100), GETDATE(), 8) >= optime1) "+
            "and (optime2 = '' or optime2 is null or CONVERT(varchar(100), GETDATE(), 8) <= optime2)",
					new Object[] { login, pass });
			if (user == null) {
				user = User.findFirst(User.class, "login=? and password=?",
								new Object[] { login, pass });
				if (user != null){
				    result.put("failure", true);
				    result.put("errors", "用户名目前不在工作时间，不能登录系统。");
				}else{
					result.put("failure", true);
				    result.put("errors", "用户名或者密码错误。");
				}
			} else {
				if ((user.getDepartment() == null) || (!user.getDepartment().getActivated().equals("1")))
				{
					result.put("failure", true);
					result.put("errors", "用户没有单位信息或者是用户单位没有激活。");
					return result;
				}
				
				Zjlist zjlist = Zjlist.findFirst(Zjlist.class," id = ? and (expiredate = '' or expiredate is null or  GETDATE() <= expiredate) ",new Object[]{ user.getDepartmentid()});
				if (zjlist == null)
				{
					result.put("failure", true);
					String errmsg = user.getDepartment().getExpirefailmsg();
					if (errmsg.equals("")) errmsg = "用户单位已过超过使用期限，请联系管理员。";
					result.put("errors", errmsg);
					return result;
				}
				
				if (user.getActivated().equals("1")) {
					Session.deleteAll(Session.class, "userid=?",
							new Object[] { user.getId() });
					String sessionId = UUID.randomUUID().toString();
					Session s = new Session();
					s.setSessionid(sessionId);
					s.setUserid(user.getId());
					s.setLogintime(new java.sql.Timestamp(System
							.currentTimeMillis()));
					s.save();

					result.put("success", true);
					result.put("userName",user.getName());
					result.put("sessionId", sessionId);
				} else {
					result.put("failure", true);
					result.put("errors", "用户处于未激活状态，不能登录");
				}
			}
			return result;
		} catch (Exception ex) {
			throw new RbacException("查询过程出现错误", ex);
		}
	}

	@Override
	public void logout() throws RbacException {
		httpSession.removeAttribute("SESSION_ALL_PRIVILEGES");  //所有需要验证的权限
		httpSession.removeAttribute("SESSION_PRIVILEGES");      //拥有所有权限
		httpSession.removeAttribute("SESSION_COMP_PRIVILEGES"); //拥有控件权限
		try {
			Session.deleteAll(Session.class, "sessionid=?",
					new Object[] { getSessionId() });
		} catch (Exception ex) {
			throw new RbacException("删除会话记录过程出现错误", ex);
		}
	}

}
